package com.chang.bootplus.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chang.bootplus.base.exception.BusException;
import com.chang.bootplus.base.utils.ApiResponse;
import com.chang.bootplus.base.utils.BeanUtil;
import com.chang.bootplus.entity.*;
import com.chang.bootplus.mapper.ProductMapper;
import com.chang.bootplus.mapper.ProductUnitMapper;
import com.chang.bootplus.po.*;
import com.chang.bootplus.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chang.bootplus.vo.BusProfitDetailVO;
import com.chang.bootplus.vo.ProductUnitVO;
import com.chang.bootplus.vo.ProductVO;
import com.chang.bootplus.vo.ProfitOfProportionVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  商品信息
 * </p>
 *
 * @author ning
 * @since 2022-01-25
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ProductServiceImp extends ServiceImpl<ProductMapper, Product> implements ProductService {

    final ProductDetailsService productDetailsService;
    final ProductPicturesService productPicturesService;
    final ProductUnitMapper productUnitMapper;
    final ProductUnitService productUnitService;
    final ProductCatesDetailsService productCatesDetailsService;

    @Override
    public ApiResponse<Void> addProduct(ProductPO po) {
//        Collection<String> values = po.getMapDetails().values();
//        List<String> listDetails = (List<String>) values;
        List<String> listDetails = new ArrayList<> (po.getMapDetails().values());
        if(listDetails.stream().allMatch( detail ->
                productDetailsService.getOne(new LambdaQueryWrapper<ProductDetails>().eq(ProductDetails::getMessage,detail))!=null
        )){
            Long proId = productDetailsService.getOne(new LambdaQueryWrapper<ProductDetails>().eq(ProductDetails::getMessage, listDetails.get(0))).getProId();
            Product one = getOne(new LambdaQueryWrapper<Product>().eq(Product::getId, proId));
            if(one.getProname().equals(po.getProname()) && one.getUserId().equals(po.getUserId()) ) {
                one.setStock(one.getStock() + po.getAddCount()).setAddTime(LocalDateTime.now());
                updateById(one);
                return new ApiResponse().setReMsg("原先存储过该商品，现将其数量叠加");
            }
        }

        //1.UUID生成32位数
        String uuid32 = UUID.randomUUID().toString().replace("-", "");
        //2.然后截取前面或后面16位
        String uuid16 = uuid32.substring(0, 16);
        Product product = BeanUtil.beanA2beanB(po, Product.class);
        product.setAddTime(LocalDateTime.now()).setProNo(uuid16).setStock(po.getAddCount());
        save(product);
        Long proId = getOne(new LambdaQueryWrapper<Product>().eq(Product::getProNo, product.getProNo())).getId();

        List<String> listPictures = po.getListPictures();

//        listDetails.stream().forEach(detail ->{
//            productDetailsService.save(new ProductDetails().setProId(proId).setMessage(detail).setProCateDetailId(integers.));
//        });

        for (Map.Entry<Long, String> entry : po.getMapDetails().entrySet()) {
            Long mapKey = entry.getKey();
            String mapValue = entry.getValue();
            productDetailsService.save(new ProductDetails().setProId(proId).setMessage(mapValue).setProCateDetailId(mapKey));
        }

        listPictures.stream().forEach(picture ->{
            productPicturesService.save(new ProductPictures().setPictureUrl(picture).setProId(proId));
        });

        ProductUnit unit = productUnitService.getOne(new LambdaQueryWrapper<ProductUnit>().eq(ProductUnit::getId, po.getCategoryIdFour()));
        if(unit == null){
            ProductUnit productUnit = BeanUtil.beanA2beanB(po, ProductUnit.class);
            productUnit.setId( po.getCategoryIdFour());
            productUnitService.save(productUnit);
        }

        return new ApiResponse().setReMsg("存储成功");
    }

    @Override
    public ApiResponse<Void> updateProduct(ProductListPO po) {
        Map<Long, String> mapDetails = po.getMapDetails();
        Collection<String> values = mapDetails.values();
        List<String> listDetails = (List<String>) values;
        List<String> listPictures = po.getListPictures();

        boolean remove1 = true , remove2 = true;
        if(listDetails != null && listDetails.size() != 0){
            remove1 = productDetailsService.remove(new LambdaQueryWrapper<ProductDetails>().eq(ProductDetails::getProId, po.getId()));
        }
        if(listPictures != null && listPictures.size() != 0){
            remove2 = productPicturesService.remove(new LambdaQueryWrapper<ProductPictures>().eq(ProductPictures::getProId, po.getId()));
        }

        if(!remove1 || !remove2){
            throw new BusException("更新失败");
        }

        listPictures.stream().forEach(picture ->{
            productPicturesService.save(new ProductPictures().setProId(po.getId()).setPictureUrl(picture));
        });

//        listDetails.stream().forEach(detail ->{
//            productDetailsService.save(new ProductDetails().setProId(po.getId()).setMessage(detail));
//        });

        //添加map
        for (Map.Entry<Long, String> entry : po.getMapDetails().entrySet()) {
            Long mapKey = entry.getKey();
            String mapValue = entry.getValue();
            productDetailsService.save(new ProductDetails().setProId(po.getId()).setMessage(mapValue).setProCateDetailId(mapKey));
        }

        //创建商品单元
        if(getOne(new LambdaQueryWrapper<Product>().eq(Product::getCategoryIdFour,po.getCategoryIdFour())) == null){
            ProductUnit productUnit = BeanUtil.beanA2beanB(po, ProductUnit.class);
            productUnit.setId( po.getCategoryIdFour() );
            productUnitService.save(productUnit);
        }

        Product product = BeanUtil.beanA2beanB(po, Product.class);
        boolean b = updateById(product);
        if (!b){
            throw new BusException("更新失败");
        }

        return new ApiResponse().setReMsg("更新成功");
    }

    @Override
    public ApiResponse<Void> deleteProduct(ProductIdPO po) {
        boolean remove1 = productDetailsService.remove(new LambdaQueryWrapper<ProductDetails>().eq(ProductDetails::getProId, po.getId()));
        boolean remove2 = productPicturesService.remove(new LambdaQueryWrapper<ProductPictures>().eq(ProductPictures::getProId, po.getId()));

        if(!remove1 || !remove2){
            throw new BusException("删除失败");
        }
        Product one = getOne(new LambdaQueryWrapper<Product>().eq(Product::getId, po.getId()));
        boolean b = removeById(po.getId());
        if (!b){
            throw new BusException("删除失败");
        }

        if(getOne(new LambdaQueryWrapper<Product>().eq(Product::getCategoryIdFour,one.getCategoryIdFour())) == null){
            boolean b1 = productUnitService.remove(new LambdaQueryWrapper<ProductUnit>().eq(ProductUnit::getId,one.getCategoryIdFour()));
            if (!b1){
                throw new BusException("删除失败");
            }
        }
        return new ApiResponse().setReCode("删除成功");
    }

    @Override
    public ApiResponse<ProductUnitVO> listProduct(ProductSelPO po) {
        po.setPageNumber(po.getPageNumber()-1);
        List<ProductUnit> productUnits = productUnitMapper.listProductUnit(po);

        List<ProductUnitVO> ProductUnitVOS = productUnits.stream().map(productUnit ->
                BeanUtil.beanA2beanB(productUnit, ProductUnitVO.class).
                        setList(BeanUtil.listA2ListB(
                                        list(new LambdaQueryWrapper<Product>().eq(Product::getCategoryIdFour, productUnit.getId()))
                                        , ProductVO.class).stream().map(productVO -> {
                                            List<ProductDetails> list1 = productDetailsService.list(new LambdaQueryWrapper<ProductDetails>()
                                                    .eq(ProductDetails::getProId, productVO.getId()));

                                            //  将查询出来的 商品详情集合进行进一步的封装，封装为 k-v形式的商品详情给前端 ， 这样看起来更方便
                                    Map<String, String> collect1 = list1.stream().collect(Collectors.toMap(productDetails ->
                                            productCatesDetailsService.getOne(new LambdaQueryWrapper<ProductCatesDetails>()
                                                    .eq(ProductCatesDetails::getId,productDetails.getProCateDetailId())).getMessage(),
                                            ProductDetails::getMessage));
                                            //就是把商品详情表和商品分类详情表联系起来，呈现出  “ '口味'： '香辣'  ”


                                    List<ProductPictures> list2 = productPicturesService.list(new LambdaQueryWrapper<ProductPictures>()
                                                    .eq(ProductPictures::getProId, productVO.getId()));
                                            List<String> collect2 = list2.stream().map(a -> a.getPictureUrl()).collect(Collectors.toList());

                                            ProductVO productVO1 = productVO.setMapDetails(collect1).setListPictures(collect2);
                                            return productVO1;
                                        }
                                ).collect(Collectors.toList())
                        )
        ).collect(Collectors.toList());

        return new ApiResponse<>(ProductUnitVOS);
    }

    @Override
    public ApiResponse<ProductVO> getProductById(ProductIdPO po) {
        Product one = getById(po.getId());
        if( one == null ){
            throw new BusException("该商品id未查询到商品");
        }
        ProductVO productVO = BeanUtil.beanA2beanB(one, ProductVO.class);
        List<ProductDetails> list1 = productDetailsService.list(new LambdaQueryWrapper<ProductDetails>()
                .eq(ProductDetails::getProId, po.getId()));

        // 和listProduct方法转换商品详情一样
        Map<String, String> collect1 = list1.stream().collect(Collectors.toMap(productDetails ->
                        productCatesDetailsService.getOne(new LambdaQueryWrapper<ProductCatesDetails>()
                                .eq(ProductCatesDetails::getId,productDetails.getProCateDetailId())).getMessage(),
                ProductDetails::getMessage));

        List<ProductPictures> list2 = productPicturesService.list(new LambdaQueryWrapper<ProductPictures>()
                .eq(ProductPictures::getProId, po.getId()));
        List<String> collect2 = list2.stream().map(a -> a.getPictureUrl()).collect(Collectors.toList());

        productVO.setMapDetails(collect1).setListPictures(collect2).setCategoryId(productUnitService
                .getOne(new LambdaQueryWrapper<ProductUnit>().eq(ProductUnit::getId,one.getCategoryIdFour())).getCategoryIdThree());
        //  查单个商品时展示该商品的三级分类id，也就是最低等级的分类id就行    不用展示四级id，因为四级id是商品单元id，是属于比较隐秘的


        return new ApiResponse<>(productVO);
    }

    @Override
    public ApiResponse<ProfitOfProportionVO> calProfitOfProportion(UserIdPO po) {
        List<Product> list = list(new LambdaQueryWrapper<Product>().eq(Product::getUserId, po.getUserId()));
        if(list == null || list.size() == 0){
            throw new BusException("该商家没有添加自己的商品");
        }
        double sumProfit = 0.0;
        for (Product product : list) {
            sumProfit += product.getSellnum() * product.getProfit().doubleValue();
        }
        List<BusProfitDetailVO> busProfitDetails = new ArrayList<>();

        double finalSumProfit = sumProfit;
        List<BusProfitDetailVO> collect = list.stream().map(product -> new BusProfitDetailVO()
                .setProfitPercent((product.getSellnum() * product.getProfit().doubleValue()) / finalSumProfit).setProname(product.getProname())
                .setId(product.getId())).collect(Collectors.toList());

        ProfitOfProportionVO profitOfProportionVO = new ProfitOfProportionVO();
        profitOfProportionVO.setBusId(po.getUserId()).setBusProfitDetails(collect);
        return new ApiResponse<>(profitOfProportionVO);
    }
}
